<?php

namespace sffi\recovery\Core;

use sffi\recovery\Exception\{EngineTypeException, FieldExistException, FileNotException};
use sffi\recovery\Constant\TableConstant;

class TableEntity
{
    /**
     * 表名
     * @var string $name
     */
    protected $name = '';
    /**
     * 表字段数组
     * @var FieldEntity[] $fields
     */
    protected $fields = [];
    /**
     * 索引数组
     * @var IndexEntity[] $indexs
     */
    protected $indexs = [];
    /**
     * 引擎
     * @var string $engine
     */
    protected string $engine;

    /**
     * 初始化表
     */
    public function __construct($name, $fields = [], $indexs = [], $engine = 'Innodb')
    {
        $this->name = $name;
        $this->fields = $fields;
        $this->indexs = $indexs;
        $this->setEngine($engine);
    }

    /**
     * 设置数据库表名
     * @param string $name
     */
    public function setName(string $name): self
    {
        $this->name = $name;
        return $this;
    }

    /**
     * 通过字段实体增加字段
     * @param FieldEntity $filed
     */
    public function addFieldEntity(FieldEntity $filed): self
    {
        $this->fields[] = $filed;
        return $this;
    }

    /**
     * 通过参数创建字段实体
     * @param string $name 字段名
     * @param string $type 字段类型
     * @param int $length 字段长度
     * @param bool $isAutoIncrement 是否自增长
     * @param string|null $default 默认值
     * @param bool $key 是否是主键
     * @param string $remark 字段说明/备注
     */
    public function addField(string $name, string $type, int $length, bool $isAutoIncrement = false, string $default = null, bool $key = false, string $remark = '')
    {
        if (isset($this->fields[$name])) {
            throw new FieldExistException();
        }
        $typeConst = 'TYPE_FIELD_' . strtoupper($type);
        if (!defined("\\sffi\\recovery\\Constant\\FieldConstant::{$typeConst}")) {
            throw new \Exception('不存在该数据类型：'."`{$this->name}`.$name-".$type);
        }
        $field = new FieldEntity($name, $type, $length, $default, $remark);
        $field->setKey($isAutoIncrement ?: $key);
        $field->setIsAutoIncrement($isAutoIncrement);
        $this->fields[$name] = $field;
    }

    /**
     * 新增索引
     * @param string $name 索引名称
     * @param string $field 索引字段
     * @param string $type 索引类型
     * @param string $method 索引方式
     * @param string $remark 索引说明/备注
     */
    public function addIndex(string $name, string $field, string $type, string $method = 'HASH', string $remark = '')
    {
        $this->indexs[] = new IndexEntity($name, $field, $type, $method, $remark);
    }

    /**
     * 获取表引擎
     * @return string
     */
    public function getEngine(): string
    {
        return $this->engine;
    }

    /**
     * 设置表引擎
     * @param string $engine
     */
    public function setEngine(string $engine): void
    {
        foreach (TableConstant::ENGINE as $definedEngine) {
            if (strtolower($engine) == strtolower($definedEngine)) {
                $this->engine = $engine;
                return ;
            }
        }
        throw new EngineTypeException();
    }

    /**
     * 生成mysql语句
     */
    public function generalSql(): string
    {
        $sql = sprintf('CREATE TABLE `%s` (', $this->name);
        foreach ($this->fields as $field) {
            $sql .= $field->generalSql();
        }
        foreach ($this->indexs as $index) {
            $sql .= $index->generalSql();
        }
        $sql = substr($sql, 0, -1);
        $sql .= sprintf(') ENGINE=%s;', $this->engine);
        return $sql;
    }

}